package com.iflytek.uoamp.notify.core.server;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Timer;

import com.iflytek.uoamp.notify.core.adapter.NotifyTask;
import org.slf4j.Logger;

import com.iflytek.uoamp.common.notify.constant.ConfigName;
import com.iflytek.uoamp.common.notify.util.Configurator;
import com.iflytek.uoamp.common.notify.util.LogbackInstance;
import com.iflytek.uoamp.notify.core.adapter.AsyncTask;
import com.iflytek.uoamp.notify.core.adapter.ProtoclAdapter;
import com.iflytek.uoamp.notify.core.dump.DumpTask;
import com.iflytek.uoamp.notify.core.handler.HttpRequestHandler;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public final class NotifyServer {

	//linux下
	private static final String NOTIFY_CONF_FILE = ConfigName.NOTIFY_CONF_FILE;
	
    private int port;
    
    private static final Logger logger = LogbackInstance.getInstance().getLogger(NotifyServer.class);
    
    public NotifyServer(int port) {
        this.port = port;
    }
    
    public static void main(String[] args) throws Exception {
    	int port = 9000;
    	//读取配置文件
    	loadProperties();
        try {
        	port = Integer.parseInt(Configurator.getInstance().getPropertyByKey("notify_start_port", "9000"));
		} catch (Exception exception) {
			logger.error("Notify server parameter port parse error,use default port 9000!" + exception.getMessage());
		}
    
        
        new NotifyServer(port).run();
    }
    
    public void run() throws Exception{
        init();
        EventLoopGroup boosGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(boosGroup, workerGroup)
            	.channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>() {

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        //HTTP响应编码解码
                        ch.pipeline().addLast(new HttpServerCodec());
                        ch.pipeline().addLast(new HttpObjectAggregator(65536));
                        // ltzeng 用于请求捕获，如果是需要处理的内容，则丢给下个Handler
                        ch.pipeline().addLast(new HttpRequestHandler());
                        // ltzeng 协议适配，初步解码并适配到具体的处理类中
                        ch.pipeline().addLast(new ProtoclAdapter());
                    }
                });
            
            Channel ch = b.bind(port).sync().channel();
            logger.info(NotifyServer.class.getSimpleName() + " started and listen on " + ch.localAddress());
            ch.closeFuture().sync();
        } finally {
            destroy();
            boosGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
    
    private void init() {
    	// 读取配置文件存储在单例Configurator.getInstance()中
        // 启动dump定时任务
        startTimer();
        
        // add by ltzeng 采用插件发送告警

//        AsyncTask task = AsyncTask.getInstance();
        NotifyTask task = NotifyTask.getInstance();
        Thread t = new Thread(task);
        t.start();

    }
    
    private void destroy() {
    }
    
    private static void loadProperties() {
        Properties prop = new Properties();
        InputStream in = null;
        try {
        	//linux系统下
        	in = new FileInputStream(NOTIFY_CONF_FILE);
            InputStreamReader reader = new InputStreamReader(in, "UTF-8");
            logger.info("Notify configuration file ========================="+NOTIFY_CONF_FILE);
            prop.load(reader);
            Enumeration<?> allName = prop.keys();
            while (allName.hasMoreElements()) {
                String key = (String) allName.nextElement();
                String value = (String) prop.get(key);
                Configurator.getInstance().setProperty(key, value);
            }
            reader.close();
        } catch (Exception e) {
            logger.error("init notify properties error " + e.getMessage(), e);
        }finally{
            try {
                if(in!=null){
                	in.close();
                }
            } catch (IOException e) {
            	logger.error("close notify properties file stream error " + e.getMessage(), e);
            }
        }
    }
    
    private void startTimer() {
        int retryInterval = Configurator.getInstance().getPropertyByKey(ConfigName.RETRY_INTERVAL, 10);
        Timer timer = new Timer();
        long period = retryInterval * 60 * 1000L;
        timer.schedule(new DumpTask(), period, period);
    }

}
